#include "mc31xx_hal_spi.h"
#include "MC3172.h"

//目前芯片仅支持数据位8
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
{
    uint32_t temp1,temp2;//用于计算时钟
    uint32_t ClockDivision;
    uint32_t SpiClock;
    uint32_t reg_iocr=0;
    

    //校验参数
    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));
    
    //计算频率
    temp1=hspi->Init.BaudRate*100;
    temp2=SYS_CORE_CLK/temp1;
    if(temp2<2)             {ClockDivision= INTDEV_CLK_IS_CORECLK;SpiClock=SYS_CORE_CLK;}
    else if(temp2<4)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2;SpiClock=SYS_CORE_CLK/2;}
    else if(temp2<8)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4;SpiClock=SYS_CORE_CLK/4;}
    else if(temp2<16)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8;SpiClock=SYS_CORE_CLK/8;}
    else if(temp2<32)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16;SpiClock=SYS_CORE_CLK/16;}
    else if(temp2<64)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV32;SpiClock=SYS_CORE_CLK/32;}
    else if(temp2<128)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV64;SpiClock=SYS_CORE_CLK/64;}
    else if(temp2<256)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV128;SpiClock=SYS_CORE_CLK/128;}
    else if(temp2<512)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV256;SpiClock=SYS_CORE_CLK/256;}
    else if(temp2<1024)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV512;SpiClock=SYS_CORE_CLK/512;}
    else if(temp2<2048)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV1024;SpiClock=SYS_CORE_CLK/1024;}
    else if(temp2<4096)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2048;SpiClock=SYS_CORE_CLK/2048;}
    else if(temp2<8192)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4096;SpiClock=SYS_CORE_CLK/4096;}
    else if(temp2<16384)    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8192;SpiClock=SYS_CORE_CLK/8192;}
    else                    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16384;SpiClock=SYS_CORE_CLK/16384;}
       
    //寄存器配置
    hspi->Instance->CR=INTDEV_RUN | INTDEV_IS_GROUP0 | ClockDivision;
    if(hspi->Init.Mode==SPI_MODE_MASTER){
        if(hspi->Init.PinMISO!=HAL_PIN_UNUSED){
            hspi->Instance->ICR=hspi->Init.PinMISO-1;
            reg_iocr|=0X3<<((hspi->Init.PinMISO-1)<<3);
        }   
        if(hspi->Init.PinMOSI!=HAL_PIN_UNUSED){
            hspi->Instance->OCR=(4<<((hspi->Init.PinMOSI-1)*4+16))|0x33330000|(0<<((hspi->Init.PinMOSI-1)*4));
            reg_iocr|=1<<((hspi->Init.PinMOSI-1)<<3);
        }   
        if(hspi->Init.PinCLK!=HAL_PIN_UNUSED){
            hspi->Instance->OCR|=(4<<((hspi->Init.PinCLK-1)*4+16))|0x33330000|(1<<((hspi->Init.PinCLK-1)*4));
            reg_iocr|=1<<((hspi->Init.PinCLK-1)<<3);
        }  
    }
    else{       //从设备

    }

    hspi->Instance->CR1=0x00000003|hspi->Init.Mode|hspi->Init.CLKPolarity|hspi->Init.CLKPhase|hspi->Init.TxFirstBit|hspi->Init.RxFirstBit;           
    hspi->Instance->CR2=(((SpiClock/hspi->Init.BaudRate)-1)<<8)+(SpiClock/hspi->Init.BaudRate)/2-2;
    hspi->Instance->IOCR=reg_iocr;

    //接收缓冲指针
    hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;
      
    return HAL_OK;
}

HAL_StatusTypeDef HAL_SPI_SetSpeed(SPI_HandleTypeDef *hspi,uint32_t BaudRate)
{
    uint32_t temp1,temp2;//用于计算时钟
    uint32_t ClockDivision;
    uint32_t SpiClock;

    //校验参数
    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));
    
    //计算频率
    hspi->Init.BaudRate=BaudRate;
    temp1=hspi->Init.BaudRate*100;
    temp2=SYS_CORE_CLK/temp1;
    if(temp2<2)             {ClockDivision= INTDEV_CLK_IS_CORECLK;SpiClock=SYS_CORE_CLK;}
    else if(temp2<4)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2;SpiClock=SYS_CORE_CLK/2;}
    else if(temp2<8)        {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4;SpiClock=SYS_CORE_CLK/4;}
    else if(temp2<16)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8;SpiClock=SYS_CORE_CLK/8;}
    else if(temp2<32)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16;SpiClock=SYS_CORE_CLK/16;}
    else if(temp2<64)       {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV32;SpiClock=SYS_CORE_CLK/32;}
    else if(temp2<128)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV64;SpiClock=SYS_CORE_CLK/64;}
    else if(temp2<256)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV128;SpiClock=SYS_CORE_CLK/128;}
    else if(temp2<512)      {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV256;SpiClock=SYS_CORE_CLK/256;}
    else if(temp2<1024)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV512;SpiClock=SYS_CORE_CLK/512;}
    else if(temp2<2048)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV1024;SpiClock=SYS_CORE_CLK/1024;}
    else if(temp2<4096)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV2048;SpiClock=SYS_CORE_CLK/2048;}
    else if(temp2<8192)     {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV4096;SpiClock=SYS_CORE_CLK/4096;}
    else if(temp2<16384)    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV8192;SpiClock=SYS_CORE_CLK/8192;}
    else                    {ClockDivision= INTDEV_CLK_IS_CORECLK_DIV16384;SpiClock=SYS_CORE_CLK/16384;}
       
    //寄存器配置
    hspi->Instance->CR=INTDEV_RUN | INTDEV_IS_GROUP0 | ClockDivision;
    hspi->Instance->CR2=(((SpiClock/hspi->Init.BaudRate)-1)<<8)+(SpiClock/hspi->Init.BaudRate)/2-2;

    return HAL_OK;
}

HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
{
    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));

    hspi->Instance->IOCR=0U;
    hspi->Instance->CR=0U;

    return HAL_OK;
}

HAL_StatusTypeDef HAL_SPI_RxFIFO_Clear(SPI_HandleTypeDef *hspi)
{
    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));

    hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;

    return HAL_OK;
}

/*SPI发送   使用fifo，使数据高效传输，但可能会导致接收错乱，建议仅发送时使用
参数：  hspi    spi对象指针
        pData   发送缓存指针
        Size    发送长度
        Timeout 发送超时ms
返回值： HAL_OK
*/
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
{
    uint32_t start_tick=CORE_CNT;
    uint32_t ticks= 1000 * SYS_CORE_CLK_MHZ>>2;

    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));
    assert_param(pData!=NULL);
    
    //数据传输
    while (Size--) {
        while ((hspi->Instance->TSR&0xFF)==(((hspi->Instance->TSR&0xFF00)>>8)^8)) { //缓冲区没有溢出的情况下继续向缓冲区填数据
            if(Timeout!=HAL_WAIT_FOREVER){
                if(CORE_CNT-start_tick>=ticks) {
                    start_tick=CORE_CNT;
                    Timeout--;
                    if(Timeout==0){
                        return HAL_TIMEOUT;
                    }  
                }
            }
        }
        *(volatile u32*)(((volatile u32)&hspi->Instance->ITDR0)+ ((hspi->Instance->TSR&0x7)<<3)) = *pData++;   
    }
    
    // while((uint32_t)&hspi->Instance->RSR&((uint32_t)1<<24)){}     //等待数据传输完成，更新读指针，丢弃掉发送期间收到的数据
    // hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;
    
    return HAL_OK;
}

/*SPI发送接收
参数：  hspi        spi对象指针
        pTxData     发送缓存指针
        pRxData     接收缓存指针
        Size        数据长度
        Timeout 发送超时ms 未实装
返回值： HAL_OK
*/
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
{
    uint16_t txcount=0;
    uint16_t rxcount=0;

    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));
    // assert_param(pTxData!=NULL);  
    // assert_param(pRxData!=NULL);  
    
    while((uint32_t)&hspi->Instance->TSR&((uint32_t)1<<18)){}         //确保读指针位置正确
    hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;  
    
    while (txcount++<Size) {
        while ((hspi->Instance->TSR&0xFF)==(((hspi->Instance->TSR&0xFF00)>>8)^8)) {} //缓冲区没有溢出的情况下持续向缓冲区填数据
        if(hspi->RxFifoPoint!=(hspi->Instance->RWPR&0xF)){  //写指针发生变化，说明有数据了
            if(pRxData){
                pRxData[rxcount]= (*(volatile u32*)(((volatile u32)&hspi->Instance->RDR0)+((hspi->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据
            }     
            rxcount++;
            hspi->RxFifoPoint=++hspi->RxFifoPoint&0x0f;
        }
        if(pTxData){
            *(volatile u32*)(((volatile u32)&hspi->Instance->ITDR0)+ ((hspi->Instance->TSR&0x7)<<3)) = *pTxData++;    
        }
        else{
            *(volatile u32*)(((volatile u32)&hspi->Instance->ITDR0)+ ((hspi->Instance->TSR&0x7)<<3)) = 0xFF;    
        }
    }
    while(rxcount<Size){
        if(hspi->RxFifoPoint!=(hspi->Instance->RWPR&0xF)){  //写指针发生变化，说明有数据了
            if(pRxData){
                pRxData[rxcount]= (*(volatile u32*)(((volatile u32)&hspi->Instance->RDR0)+((hspi->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据 
            }    
            rxcount++;
            hspi->RxFifoPoint=++hspi->RxFifoPoint&0x0f;
        }
    }
    
    return HAL_OK;
}

/*SPI发送接收单字节
参数：  hspi        spi对象指针
        pTxData     发送缓存指针
        pRxData     接收缓存指针
        Size        数据长度
        Timeout 发送超时ms 未实装
返回值： HAL_OK
*/
uint8_t HAL_SPI_TransmitReceiveByte(SPI_HandleTypeDef *hspi, uint8_t TxData, uint32_t Timeout)
{
    uint8_t rxdata=0;

    assert_param(hspi!=NULL);
    assert_param(IS_SPI_INSTANCE(hspi->Instance));
    
    while((uint32_t)&hspi->Instance->RSR&((uint32_t)1<<24)){}         //确保读指针位置正确
    hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;    
     
    *(volatile u32*)(((volatile u32)&hspi->Instance->ITDR0)+ ((hspi->Instance->TSR&0x7)<<3)) = TxData;    
    
    while(hspi->RxFifoPoint==(hspi->Instance->RWPR&0xF)){}  //等待数据
    rxdata= (*(volatile u32*)(((volatile u32)&hspi->Instance->RDR0)+((hspi->RxFifoPoint&0x7)<<3)));  //读取指针指向的数据     
    hspi->RxFifoPoint=hspi->Instance->RWPR&0xF;    
    
    return rxdata;
}


